Skip to content

Conversation

@samwillis
Copy link
Collaborator

@samwillis samwillis commented Jul 7, 2025

replaces #216, stacked on #185

This allows you to predefine a query with this syntax:

import { Query } from '@tanstack/db'

const myQuery = new Query()
  .from(...)
  .where(...)

then use it with:

const liveQueryCollection = createCollection(liveQueryCollectionOptions({
  query: myQuery,
}))
// or
const { data } = useLiveQuery({
  query: myQuery,
})

It also enables creating reusable callback functions for use in where, groupBy, select etc. with a Ref<MyType> to correctly cast to the type for the expression builder functions.

import type { Ref } from '@tanstack/db'

const userIsAdult = ({ user }: { user: Ref<User> }) => gt(user.age, 18)

const userIsActive = ({ user }: { user: Ref<User> }) =>
  eq(user.active, true)

const userIsYoung = ({ user }: { user: Ref<User> }) => lt(user.age, 25)

// Use the predicates in a query
const myQuery = new Query()
  .from({ user: usersCollection })
  .where(userIsAdult)
  .where(userIsActive)
  .where(userIsYoung)

Or in a select:

// Define reusable select objects using defineForRow
const userBasicInfo = ({ user }: { user: Ref<User> }) => ({
  id: user.id,
  name: user.name,
  email: user.email,
})

const userNameTransforms = ({ user }: { user: Ref<User> }) => ({
  nameUpper: upper(user.name),
  nameLower: lower(user.name),
})

// Use the select objects in a query
const myQuery = new Query()
  .from({ user: usersCollection })
  .where(({ user }) => eq(user.active, true))
  .select(({ user }) => ({
    ...userBasicInfo({ user }),
    ...userNameTransforms({ user }),
    age: user.age,
  }))

@samwillis samwillis requested a review from KyleAMathews July 7, 2025 12:03
@changeset-bot
Copy link

changeset-bot bot commented Jul 7, 2025

🦋 Changeset detected

Latest commit: ff0e9f8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@tanstack/react-db Patch
@tanstack/vue-db Patch
@tanstack/db Patch
@tanstack/db-example-react-todo Patch
@tanstack/db-collections Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jul 7, 2025

@tanstack/db-example-react-todo

npm i https://pkg.pr.new/@tanstack/db@232
npm i https://pkg.pr.new/@tanstack/db-collections@232
npm i https://pkg.pr.new/@tanstack/react-db@232
npm i https://pkg.pr.new/@tanstack/vue-db@232

commit: ff0e9f8

@github-actions
Copy link
Contributor

github-actions bot commented Jul 7, 2025

Size Change: -12 B (-0.04%)

Total Size: 30.3 kB

Filename Size Change
./packages/db/dist/esm/index.js 528 B -35 B (-6.22%)
./packages/db/dist/esm/query/builder/ref-proxy.js 842 B -9 B (-1.06%)
./packages/db/dist/esm/query/compiler/group-by.js 2.09 kB +3 B (+0.14%)
./packages/db/dist/esm/query/ir.js 318 B +6 B (+1.92%)
./packages/db/dist/esm/query/live-query-collection.js 2.04 kB +23 B (+1.14%)
ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection.js 7.86 kB
./packages/db/dist/esm/deferred.js 230 B
./packages/db/dist/esm/errors.js 150 B
./packages/db/dist/esm/optimistic-action.js 294 B
./packages/db/dist/esm/proxy.js 3.75 kB
./packages/db/dist/esm/query/builder/functions.js 531 B
./packages/db/dist/esm/query/builder/index.js 3.4 kB
./packages/db/dist/esm/query/compiler/evaluators.js 1.34 kB
./packages/db/dist/esm/query/compiler/index.js 1.42 kB
./packages/db/dist/esm/query/compiler/joins.js 1.15 kB
./packages/db/dist/esm/query/compiler/order-by.js 933 B
./packages/db/dist/esm/query/compiler/select.js 657 B
./packages/db/dist/esm/SortedMap.js 1.24 kB
./packages/db/dist/esm/transactions.js 1.51 kB

compressed-size-action::db-package-size

@github-actions
Copy link
Contributor

github-actions bot commented Jul 7, 2025

Size Change: 0 B

Total Size: 972 B

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 152 B
./packages/react-db/dist/esm/useLiveQuery.js 820 B

compressed-size-action::react-db-package-size

@kevin-dp
Copy link
Contributor

kevin-dp commented Jul 7, 2025

@samwillis LGTM. One question i have though is why we need to wrap the query in an object with a query key?

const { data } = useLiveQuery({
  query: myQuery,
})

Couldn't we just pass the query as an argument directly without wrapping?

@samwillis
Copy link
Collaborator Author

Couldn't we just pass the query as an argument directly without wrapping?

The wrapping object is currently the liveQueryCollectionOptions, so there is more we can pass in there. I left it as either the callback or this options object to simplify the overloads and not add another. We can always add it later if there is desire to.

Base automatically changed from query2 to main July 7, 2025 13:46
@samwillis samwillis merged commit e478d53 into main Jul 7, 2025
4 checks passed
@samwillis samwillis deleted the samwillis/composables branch July 7, 2025 14:18
@github-actions github-actions bot mentioned this pull request Jul 7, 2025
cursor bot pushed a commit that referenced this pull request Jul 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants